<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>css 透视， 曲面照片墙(照片间距)</title>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <style>
      #app {
        width: 500px;
        margin: 0 auto;
      }
      .container {
        width: 300px;
        height: 300px;
        border: 2px solid red;
        background-color: silver;
        margin: 100px auto;
        position: relative;
      }
      .container .box {
        width: 100%;
        height: 100%;
        background-color: aquamarine;
      }
      .row {
        transform-style: preserve-3d;
        width: 20%;
        height: 20%;
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
      }
      .row .item {
        position: absolute;
        width: 100%;
        height: 100%;
        background-color: aquamarine;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 20px;
        color: #fff;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div
        class="container"
        :style="{
        perspective: perspective + 'px'
      }"
      >
        <div
          class="box"
          :style="{
        transform: 'rotateY(45deg)'
      }"
        ></div>
      </div>
      <ul>
        <li>
          perspective
          <input type="number" v-model="perspective" step="100" />
          {{perspective}}
        </li>
      </ul>
      <dl>
        <dt>基础:box 只移动z轴时 显示(投影)大小为 container 的一半</dt>
        <dd>摄像机正对container 中心点, 距离为 perspective;</dd>
        <dd>
          摄像机 看到的 box 在container 上的投影恰好是container 长度的一半大,
          即摄像机与box边缘的连线或延长线在 container 上的点距离 container中心点距离为 container
          尺寸的一半
        </dd>
        <dd>
          三角形等比计算： (-box$Z) + perspective = 2perspective ； 所以box$z = -perspective;备注
          近大远小 z轴正向指向摄像机, 为负值时远小
        </dd>
      </dl>
      <dl>
        <dt>
          基础:perspective 未设置 时，其值不是0 ，使用平面算法，此时 z轴变化无影响，直接垂直投射
          而不是 摄像投射(前者投影线垂直于平面，后者总经过摄像机)
        </dt>
        <dt>基础:perspect-3d vs flat；</dt>
        <dd>在哪用: 子元素也3d变换，缺省情况子元素的3d变化无效会flat到当前元素上</dd>
      </dl>
      <dl>
        <dt>曲面照片墙基础:</dt>
        <dt>
          一行内 每个item 离
          某个圆心相同距离(半径radius),且垂直于中心与圆心的连线:item.transform:rotateY((i * diff)
          deg) translateZ(radius)
        </dt>
        <dt>问题：各行间距怎么控制?</dt>
        <dd>曲面-弧度，非曲面-线性</dd>
        <dt>问题：设置 translateZ 避免item 范围超出 container</dt>
        <dd>最边缘与摄像机的连线在容器边缘内:</dd>
        <dd>z$container~itemEdge = cos(angle$max) * rDistance</dd>
        <dd>x$itemEdge =  sin(angle$max) * rDistance + 1/2 * cellWidth；//近似值 1/2 * cellWidth</dd>
        <dd>等比例三角形公式得到：x$itemEdge / conainerWidth <= (perspect$distance + z$container~itemEdge) / perspect$distance </dd>
        <dd>另外还要比较 y轴: </dd>
        <dd>等比例三角形公式得到：y$itemEdge / conainerHeight <= (perspect$distance + z$container~itemEdge) / perspect$distance </dd>
      </dl>
      <div
        class="container"
        :style="{
        perspective: perspective + 'px'
      }"
      >
        <div
          class="row"
          v-for="row in rowCount"
          :style="{top:`calc( 50% - (20% / 2) + ${row - (rowCount+1) / 2} * 20% + ${gapRow}px * ${row - (rowCount+1) / 2})`}"
        >
          <div
            class="item"
            v-for="(i) in itemCountPerRow"
            :style="{
            transform: `rotateY(${(i - (itemCountPerRow+1) / 2) * gapCol$angleDiff}deg) translateZ(-${rDistance}px)`
          }"
          >
            <!-- transform: `rotateY(${(i - (itemCountPerRow+1) / 2) * gapCol$angleDiff}) translateZ(-${rDistance}px)` -->
            {{i}}
          </div>
        </div>
      </div>
    </div>
    <script>
      const { createApp, ref } = Vue
      const perspective = ref(1000)
      const itemCountPerRow = 5
      const rowCount = 5
      const gapCol = 20
      const gapRow = 20
      const rDistance = 300
      createApp({
        setup() {
          const message = ref('Hello vue!')
          /* 近似计算，角度越大误差越大: 圆弧长度约等于1/2*width + gapCol + 1/2*width ;    gapCol$angleDiff * r = gapCol + cellWidth   */
          const cellWidth = 60
          const gapCol$angleDiff = (((gapCol + cellWidth) / rDistance) * 180) / Math.PI

          return {
            perspective,
            itemCountPerRow,
            rDistance,
            gapRow,
            gapCol,
            rowCount,
            gapCol$angleDiff
          }
        }
      }).mount('#app')
    </script>
  </body>
</html>
